<?php
namespace app\common\library\xilujob;


use app\common\exception\LogicException;
use app\common\library\xilujob\resume\BaseModule;
use app\common\model\xilujob\Resume;
use app\common\model\xilujob\Resume as ResumeModel;
use app\common\model\xilujob\ResumeSchameRelation;
use app\common\model\xilujob\ResumeSchema;
use app\common\model\User;
use think\Db;
use think\Exception;
use think\exception\ClassNotFoundException;
use think\Log;
use think\Request;

class ResumeLibrary {

    const MODULE_PERSONAL_INFO = 'personal_info';
    const MODULE_JOB_INTENTION = 'job_intention';
    const MODULE_EDUCATION = 'education';
    const MODULE_PROJECT = 'project';
    const MODULE_OTHER_PROJECT = 'other_project';
    const MODULE_CERTIFICATE = 'certificate';
    const MODULE_COMMUNITY = 'community';
    const MODULE_WORK = 'work';
    const MODULE_RESEARCH = 'research';
    const MODULE_AWARD = 'award';
    const MODULE_SKILL = 'skill';
    const MODULE_SUMMARY = 'summary';
    const MODULE_PERSONAL_TAG = 'personal_tag';

    const AvailableModules = [
        self::MODULE_PERSONAL_INFO => ['name'=>'个人信息','required'=>true,'relation'=>'personal'],
        self::MODULE_JOB_INTENTION => ['name'=>'求职意向','required'=>true,'relation'=>'job_intention'],
        self::MODULE_EDUCATION => ['name'=>'教育经历','required'=>false,'relation'=>'educations'],
//        self::MODULE_PROJECT => ['name'=>'项目经历','required'=>false,'relation'=>'projects'],
//        self::MODULE_CERTIFICATE => ['name'=>'技能证书','required'=>false],
//        self::MODULE_COMMUNITY => ['name'=>'社团组织经历','required'=>false],
        self::MODULE_WORK => ['name'=>'工作经验','required'=>false,'relation'=>'works'],
//        self::MODULE_RESEARCH => ['name'=>'研究经历','required'=>false],
//        self::MODULE_AWARD => ['name'=>'荣誉奖项','required'=>false],
        self::MODULE_SKILL => ['name'=>'专业技能','required'=>false,'relation'=>'skills'],
        self::MODULE_SUMMARY => ['name'=>'个人总结','required'=>false,'relation'=>'summary'],
        self::MODULE_PERSONAL_TAG => ['name'=>'个人标签', 'required'=>false,'relation'=>'personal_tags'],
    ];

    protected $model;
    protected $user;
    protected $moduleConfig;
    protected $moduleClasses;

    /**
     * Resume constructor.
     * @param \app\common\model\xilujob\Resume $resume
     * @param User $user
     * @param ResumeSchema $schema
     */
    public function __construct($resume, User $user) {
        $this->model = $resume;
        $this->user = $user;
        $modules = ResumeSchema::get_schema();

        foreach($modules as $module) {
            $this->moduleConfig[$module['schema_name']] = $module->toArray();
        }
    }

    public function __get($name) {
        if(in_array($name,['model','user','schema','template'])) {
            return $this->$name;
        }
        return null;
    }

    /**
     * @param $resume
     * @param User $user 由于大部分时候都可由登录态获取user, 可以传递进来，省去读数据库
     * @return string|static
     */
    public static function getResumeLibrary($resume, User $user=null) {

        if(!$resume instanceof ResumeModel) {
            $resume = ResumeModel::get($resume);
        }
        if(!$user || ($user->id!=$resume->user_id)) {
            $user = User::get($resume->user_id);
        }
        if(!$user || !$resume) {
            throw new Exception('参数错误');
        }

        $resumeLibrary = new static($resume, $user);
        return $resumeLibrary;
    }

    /**
     * 创建简历
     * @param $user
     * @return Resume|string
     * @throws \Exception
     */
    public static function createResume($user,$member) {
        if(! $user instanceof User) {
            $user = User::get($user);
        }
        if(!$user) {
            throw new Exception(__('invalid arguments'));
        }

        try {
            return Db::transaction(function () use ($user,$member) {
                $resumeModel = new Resume();
                $result = $resumeModel->save(['user_id' => $user->id, 'member_id'=>$member->id,'status'=>'1']);
                if (!$result) {
                    throw new Exception('创建简历失败:' . $resumeModel->getError());
                }
                $resume = new static($resumeModel,$user);
                $resume->fireModuleEvent('create_resume', $resumeModel);

                $resumeSchemaModel = (new ResumeSchameRelation());
                $result = $resumeSchemaModel->add($resumeModel);
                if(!$result){
                    throw new Exception('简历模板保存失败:' . $resumeSchemaModel->getError());
                }
                try {
                    //debug 记录创建简历时的url， 时间， 用户id
                    $file = fopen(RUNTIME_PATH.'/resume.log','a');
                    $str = sprintf('%s: %s %s', date('Y-m-d H:i:s'), Request()->url(), $user->id);
                    fwrite($file, $str."\n");
                    fclose($file);
                }catch (\Exception $e) {
                    Log::error('记录简历创建时间失败');
                }
                return $resumeModel;
            });
        }catch (\Exception $e) {
            Log::error($e->getMessage());
            throw $e;
        }
    }

    /**
     * 添加一个模块的记录,如：新建项目经历
     * @param $moduleName
     * @param $data
     * @return mixed
     */
    public function add($moduleName, $data) {
        $module = $this->module($moduleName);
        $ret = $module->add($data);

        $this->updateResumeCompleteProgress();
        return $ret;
    }

    /**
     * @param string $moduleName
     * @param array $data 必须有id
     * @return mixed
     */
    public function edit($moduleName, $data) {
        $module = $this->module($moduleName);
        $ret = $module->edit($data);

        #简历进度更新
        $this->updateResumeCompleteProgress();

        return $ret;
    }

    /**
     * @param $moduleName
     * @param $id
     * @return null|string|static
     */
    public function del($moduleName, $id) {
        $module = $this->module($moduleName);
        $ret = $module->del($id);

        $this->updateResumeCompleteProgress();
        return $ret;
    }

    /**
     * @param $moduleName
     * @return BaseModule
     */
    protected function module($moduleName) {
        if(!array_key_exists($moduleName, $this->moduleConfig)) {
            throw new ClassNotFoundException("Module '$moduleName' not defined");
        }
        if(!isset($this->moduleClasses[$moduleName])) {
            $class = explode('\\',static::class);
            $class[count($class)-1] = 'resume\\'.$this->slash2camel($moduleName);
            $class = implode('\\',$class);
            $this->moduleClasses[$moduleName] = new $class($this->model);
        }
        $module = $this->moduleClasses[$moduleName];
        return $module;
    }

    /**
     * 抛出event, 尝试call 所有module的on{$eventName} method
     * @param $eventName
     * @param ResumeModel $resume
     */
    private function fireModuleEvent($eventName, ResumeModel $resume) {
        foreach($this->moduleConfig as $moduleName=>$config) {
            $methodName = 'on'.$this->slash2camel($eventName);
            $this->module($moduleName)->$methodName($resume);
        }
    }

    /**
     * 下划线名转成驼峰, com_here to ComHere
     * @param $name
     * @return string
     */
    private function slash2camel($name) {
        $parts = explode('_',$name);
        $class = '';
        foreach ($parts as $part) {
            $class .= strtoupper(substr($part,0,1)) . substr($part, 1, strlen($part)-1);
        }
        return $class;
    }

    /**
     * 更新简历完成度
     */
    private function updateResumeCompleteProgress() {
        $score = $max = 0;
        foreach($this->moduleConfig as $moduleName=>$config) {
            $methodName = 'getCompleteScore';
            $ret = $this->module($moduleName)->$methodName();
            $score += $ret['score'];
            $max += $ret['max'];
        }
        if($score>=$max) {
            $percent = 100;
        }else {
            $percent = intval($score*100/$max);
        }

        $this->model->save(['complete_percent'=>$percent,'refreshetime'=>date('Y-m-d H:i:s'),'refresh_date'=>date('Y-m-d')]);
    }

}